﻿Imports System.IO
Imports System.Xml
Imports System.Text
Imports System.Security.Cryptography
Imports System.Text.RegularExpressions
Imports System.Globalization
Imports System.Web.Script.Serialization


Public Class functions

    Public Shared APIKey As String

    Public Shared Function WRequest(ByVal URL As String, ByVal method As String, ByVal POSTdata As String) As String
        Dim responseData As String = ""
        Try
            Dim hwrequest As Net.HttpWebRequest = Net.WebRequest.Create(URL & "?" & POSTdata)
            hwrequest.Accept = "*/*"
            hwrequest.UserAgent = "http_requester/0.1"
            hwrequest.Timeout = 60000
            hwrequest.Method = method
            If hwrequest.Method = "POST" Then
                hwrequest.ContentType = "application/x-www-form-urlencoded"
                Dim encoding As New System.Text.ASCIIEncoding() 'Use UTF8 Encoding for XML requests
                Dim postByteArray() As Byte = encoding.GetBytes(POSTdata)
                hwrequest.ContentLength = postByteArray.Length
                Dim postStream As IO.Stream = hwrequest.GetRequestStream()
                postStream.Write(postByteArray, 0, postByteArray.Length)
                postStream.Close()
            End If
            Dim hwresponse As Net.HttpWebResponse = hwrequest.GetResponse()
            If hwresponse.StatusCode = Net.HttpStatusCode.OK Then
                Dim responseStream As IO.StreamReader = _
                  New IO.StreamReader(hwresponse.GetResponseStream())
                responseData = responseStream.ReadToEnd()
            End If
            hwresponse.Close()
        Catch e As Exception
            responseData = My.Resources._code_error_occured & " : " & e.Message
        End Try
        Return responseData
    End Function

    Public Shared Function MD5(ByVal input As String) As String
        Dim x As New MD5CryptoServiceProvider()
        Dim bs As Byte() = System.Text.Encoding.UTF8.GetBytes(input)
        bs = x.ComputeHash(bs)
        Dim s As New StringBuilder()
        For Each b As Byte In bs
            s.Append(b.ToString("x2").ToLower())
        Next
        Dim hash As String = s.ToString()
        Return hash
    End Function

    Public Shared Function DoLogin(ByVal server As String, mail As String, ByVal password As String) As String
        Dim wdata, encryptedXML As String
        Dim objXml As New XmlDocument

        Dim APIKey = MD5(mail & ":" & password)
        wdata = WRequest(server & "/", "POST", "api&api_key=" & APIKey)
        Try

            ' Parse JSON result given by the request result
            Dim jss = New JavaScriptSerializer()
            Dim jsonResult As Dictionary(Of String, String) = jss.Deserialize(Of Dictionary(Of String, String))(wdata)
            Dim authed = jsonResult.Item("auth").ToString

            If authed = "0" Then     ' Bad credentials
                Return "403"
            Else
                If File.Exists(Environ("AppData") & "\" & Application.ProductName & "\" & Reader.user_info_file) = False Then
                    If Directory.Exists(Environ("AppData") & "\" & Application.ProductName) = False Then
                        Directory.CreateDirectory(Environ("AppData") & "\" & Application.ProductName)
                    End If
                    ' Create user info XML file
                    ' First root element
                    objXml.LoadXml("<user></user>")
                    ' Create and define server element
                    Dim elemServer As XmlElement
                    elemServer = objXml.CreateElement("server")
                    elemServer.InnerText = server
                    ' Create and define email element
                    Dim elemMail As XmlElement
                    elemMail = objXml.CreateElement("email")
                    elemMail.InnerText = mail
                    ' Create and define password element
                    Dim elemPassword As XmlElement
                    elemPassword = objXml.CreateElement("password")
                    elemPassword.InnerText = password
                    ' Create and define language element
                    Dim elemLanguage As XmlElement
                    elemLanguage = objXml.CreateElement("language")
                    elemLanguage.InnerText = CultureInfo.CurrentCulture.ToString
                    ' Add the 4 elements to root node (user)
                    objXml.DocumentElement.AppendChild(elemServer)
                    objXml.DocumentElement.AppendChild(elemMail)
                    objXml.DocumentElement.AppendChild(elemPassword)
                    objXml.DocumentElement.AppendChild(elemLanguage)
                    ' Encrypt XML document before save it to disk
                    encryptedXML = Encrypt(objXml.InnerXml)
                    ' Save encrypted XML to disk
                    Dim objWriter As New StreamWriter(Environ("AppData") & "\" & Application.ProductName & "\" & Reader.user_info_file)
                    objWriter.WriteLine(encryptedXML)
                    objWriter.Close()
                End If
            End If
            Return APIKey
        Catch ex As Exception
            Return "KO"
        End Try
    End Function

    Public Shared Function GetFeedXML(elementsIds As String, nodeItem As String) As XmlDocument
        Dim listIds, arrIds() As String
        Dim xmlfeed, xmlreturned As New XmlDocument()
        Dim nodeReturned As XmlNodeList

        ' Create XML root
        Dim dec As XmlDeclaration = xmlfeed.CreateXmlDeclaration("1.0", Nothing, Nothing)
        xmlfeed.AppendChild(dec)
        Dim response As XmlElement = xmlfeed.CreateElement("response")
        xmlfeed.AppendChild(response)
        Dim items As XmlElement = xmlfeed.CreateElement("items")
        response.AppendChild(items)

        Try

            ' Define items batch to retrieve
            arrIds = elementsIds.Split(",")
            listIds = ""
            Dim nbitems = arrIds.Count
            Dim nbBatch50 = nbitems \ 50       ' Integer division
            Dim nbLastBatch = nbitems Mod 50    ' Remainder of division

            If nbBatch50 > 0 Then                ' Make batch of 50
                For i = 0 To nbBatch50 - 1
                    listIds = ""
                    For j = 1 + (50 * i) To 50 + (50 * i)
                        If listIds <> "" Then listIds = listIds & ","
                        listIds = listIds & arrIds(j - 1)
                    Next
                    nodeReturned = GetFeedDetails(listIds)
                    ' Insert retrieved node to main feed
                    For Each node As XmlNode In nodeReturned
                        Dim newnode = xmlfeed.ImportNode(node, True)
                        xmlfeed.DocumentElement.Item("items").AppendChild(newnode)
                    Next
                Next
            End If
            If nbLastBatch > 0 Then               ' Make last batch
                listIds = ""
                For i = (nbBatch50 * 50) To nbitems - 1
                    If listIds <> "" Then listIds = listIds & ","
                    listIds = listIds & arrIds(i)
                Next
                nodeReturned = GetFeedDetails(listIds)
                ' Insert retrieved node to main feed
                For Each node As XmlNode In nodeReturned
                    Dim newnode = xmlfeed.ImportNode(node, True)
                    xmlfeed.DocumentElement.Item("items").AppendChild(newnode)
                Next
            End If

        Catch ex As Exception
            MessageBox.Show(My.Resources._code_error_fetch_items_db & " " & ex.Message)
        End Try

        Return xmlfeed

    End Function

    ' Retrieve detail of each item
    Public Shared Function GetFeedDetails(listIds As String) As XmlNodeList
        Dim wdata, feed_id, feed_name, feed_url, group_name, group_id, is_spark As String
        Dim ObjXml As New XmlDocument
        feed_name = ""
        feed_url = ""
        group_name = ""
        group_id = ""
        is_spark = ""

        ' Retrieve items 
        ' Request : [serverURL]?api=xml&items&with_ids=[list of unread items, batch of max 50 items]
        wdata = WRequest(Reader.serverURL & "/", "POST", "api=xml&items&with_ids=" & listIds & "&api_key=" & functions.APIKey)
        ObjXml.LoadXml(wdata)
        Dim nodeItems As XmlNodeList = ObjXml.DocumentElement.SelectNodes("items/item")

        Try

            For Each node As XmlNode In nodeItems
                ' Search for name and URL of feed corresponding to feed_id, and ID and name of feed group
                feed_id = node.SelectSingleNode("feed_id").InnerText
                For i = 0 To UBound(Reader.ArrFeedsGroup)
                    If Reader.ArrFeedsGroup(i).id = feed_id Then
                        feed_name = Reader.ArrFeedsGroup(i).name
                        feed_url = Reader.ArrFeedsGroup(i).url
                        is_spark = Reader.ArrFeedsGroup(i).is_spark
                        For j = 0 To UBound(Reader.ArrSubscriptionsGroup)
                            If Reader.ArrFeedsGroup(i).id_group = Reader.ArrSubscriptionsGroup(j).id Then
                                group_id = Reader.ArrSubscriptionsGroup(j).id
                                group_name = Reader.ArrSubscriptionsGroup(j).name
                                Exit For
                            End If
                        Next
                        Exit For
                    End If
                Next
                Dim elem_feed As XmlElement = ObjXml.CreateElement("feed_name")
                elem_feed.InnerText = feed_name
                node.AppendChild(elem_feed)
                Dim elem_url_feed As XmlElement = ObjXml.CreateElement("feed_url")
                elem_url_feed.InnerText = feed_url
                node.AppendChild(elem_url_feed)
                Dim elem_is_spark As XmlElement = ObjXml.CreateElement("is_spark")
                elem_is_spark.InnerText = is_spark
                node.AppendChild(elem_is_spark)
                Dim elem_group_id As XmlElement = ObjXml.CreateElement("group_id")
                elem_group_id.InnerText = group_id
                node.AppendChild(elem_group_id)
                Dim elem_group As XmlElement = ObjXml.CreateElement("group_name")
                elem_group.InnerText = group_name
                node.AppendChild(elem_group)

            Next

        Catch ex As Exception
            MessageBox.Show(My.Resources._code_error_fetch_item_details_db & " " & ex.Message)
        End Try

        Return nodeItems

    End Function

    Public Shared Function MakeHotList() As XmlDocument
        Dim wdata, item_ids As String
        Dim ObjXml, xmlfeed As New XmlDocument
        Dim nodeLinksItems As XmlNodeList

        ' Create XML root
        Dim dec As XmlDeclaration = xmlfeed.CreateXmlDeclaration("1.0", Nothing, Nothing)
        xmlfeed.AppendChild(dec)
        Dim response As XmlElement = xmlfeed.CreateElement("response")
        xmlfeed.AppendChild(response)
        Dim links As XmlElement = xmlfeed.CreateElement("links")
        response.AppendChild(links)

        ' Retrieve items 
        ' Request : [serverURL]?api=xml&links
        ' other parameters : &page=1&range=7&offset=0-> the first page (page=1) of Hot links 
        ' for the past week (range=7) starting now (offset=0)
        wdata = WRequest(Reader.serverURL & "/", "POST", "api=xml&links&api_key=" & functions.APIKey)
        ObjXml.LoadXml(wdata)
        Dim nodeItems As XmlNodeList = ObjXml.DocumentElement.SelectNodes("links/link")

        Try

            For Each node As XmlNode In nodeItems
                ' For each link found, add to output XML the item(s) associated to the link
                ' Search for items_ids associated to links
                item_ids = node.SelectSingleNode("item_ids").InnerText
                ' Add link to output XML generated
                Dim nodeImport = xmlfeed.ImportNode(node, True)
                xmlfeed.DocumentElement.SelectSingleNode("links").AppendChild(nodeImport)
                ' Search for additionnal information associated to each item associated to the link
                nodeLinksItems = GetFeedDetails(item_ids)
                ' Add the additionnal information of each item in the XML node corresponding to the link
                For Each nodeItem As XmlNode In nodeLinksItems
                    Dim nodeImportItem = xmlfeed.ImportNode(nodeItem, True)
                    xmlfeed.DocumentElement.SelectSingleNode("links").LastChild.AppendChild(nodeImportItem)
                Next
            Next

        Catch ex As Exception
            MessageBox.Show(My.Resources._code_error_generating_hotlist & " " & ex.Message)
        End Try

        Return xmlfeed

    End Function

    Public Shared Function ChangeItemState(ByVal id, ByVal status) As String
        Dim wdata As String
        Dim timestampUTCnow = CLng(DateTime.UtcNow.Subtract(New DateTime(1970, 1, 1)).TotalMilliseconds)

        ' Change an item state
        ' Request : [serverURL]?api&manage=statuses&mark=item&as=[read/unread/saved/unsaved]&id=[id_item]&[timestamp]

        Select Case status
            ' Mark item read/unread (given status)
            Case "read"
                wdata = WRequest(Reader.serverURL & "/", "POST", "api&manage=statuses&mark=item&as=read&id=" & id & "&" & timestampUTCnow & "&api_key=" & APIKey)
            Case "unread"
                wdata = WRequest(Reader.serverURL & "/", "POST", "api&manage=statuses&mark=item&as=unread&id=" & id & "&" & timestampUTCnow & "&api_key=" & APIKey)

                ' Mark item saved/unsaved (given status)
            Case "saved"
                wdata = WRequest(Reader.serverURL & "/", "POST", "api&manage=statuses&mark=item&as=saved&id=" & id & "&" & timestampUTCnow & "&api_key=" & APIKey)
            Case "unsaved"
                wdata = WRequest(Reader.serverURL & "/", "POST", "api&manage=statuses&mark=item&as=unsaved&id=" & id & "&" & timestampUTCnow & "&api_key=" & APIKey)

                ' Ensure a return value
            Case Else
                wdata = ""
        End Select

        ' Parse JSON result given by the request result
        Dim jss = New JavaScriptSerializer()
        Dim jsonResult As Dictionary(Of String, String) = jss.Deserialize(Of Dictionary(Of String, String))(wdata)
        Dim authed = jsonResult.Item("auth").ToString

        If authed = "1" Then     ' Bad credentials
            Return "OK"
        Else
            Return "KO"
        End If

    End Function

    Public Shared Function TreeviewGetNodeByPath(ByVal treeView As TreeView, ByVal path As String) As TreeNode

        Dim tn() As TreeNode = treeView.Nodes.Find(path, True)
        If tn.Count > 0 Then Return tn(0) Else Return Nothing

    End Function

    Public Shared Function TreeviewGetNodeByTag(ByVal parentCollection As TreeNodeCollection, ByVal tag As String) As TreeNode

        Dim ret As TreeNode = Nothing
        Dim child As TreeNode

        For Each child In parentCollection 'step through the parentcollection
            If child.Tag = tag Then
                ret = child
            ElseIf child.GetNodeCount(False) > 0 Then ' if there is child items then call this function recursively
                ret = TreeviewGetNodeByTag(child.Nodes, tag)
            End If

            If Not ret Is Nothing Then Exit For 'if something was found, exit out of the for loop

        Next

        Return ret

    End Function

    Public Shared Function AddFullPathToTreeView(ByRef treeView As TreeView, ByVal strPath As String) As Boolean
        If IsNothing(treeView) OrElse treeView.IsDisposed OrElse strPath = "" Then Return False

        Dim branches() As String = strPath.Split("\")                       ' Split the path
        If Not strPath.Contains("\") Or branches.Length <= 1 Then           ' This is a root folder
            If Not IsNothing(treeView.Nodes.Find(strPath, True)) Then       ' Check to make sure the root node does not already exists.
                Return False
            Else
                treeView.Nodes.Add(strPath, strPath)                        ' Create a new root node
                Return True
            End If
        End If

        Dim ParentNode As TreeNode = Nothing
        Dim CurrentPath As String = branches(0)                             ' Root path
        For NodeIndex As Integer = 0 To (branches.Length - 1)               ' Loop through all node segments
            If ParentNode IsNot Nothing Then                                ' If we have a ParentNode then set the path using this
                CurrentPath = ParentNode.FullPath & "\" & branches(NodeIndex)
            End If
            Dim foundNodes() As TreeNode = treeView.Nodes.Find(CurrentPath, True)   ' Check if Node exists
            If foundNodes.Length <= 0 Then                                  ' If Node doesn't exist then create a new one
                Dim rootNode = New TreeNode(branches(NodeIndex))           ' Add a new  node
                If ParentNode Is Nothing Then                               ' Add node to Tree or ParentNode if it exists
                    ParentNode = treeView.Nodes.Add(CurrentPath, branches(NodeIndex))
                Else
                    ParentNode = ParentNode.Nodes.Add(CurrentPath, branches(NodeIndex))
                End If
            Else
                ParentNode = foundNodes(0)                                '  Node created previouslly so just set it as Parent
            End If
        Next
        Return True

    End Function

    Public Shared Function MailIsValid(ByVal mail_address As String) As Boolean
        Dim rexp As New Regex _
            ("^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", _
           RegexOptions.IgnoreCase)
        Return rexp.IsMatch(mail_address)
    End Function

    Public Shared Function UrlIsValid(ByVal url As String) As Boolean
        Dim is_valid As Boolean = False
        If url.ToLower().StartsWith("www.") Then url = "http://" & url

        Dim web_response As Net.HttpWebResponse = Nothing
        Try
            Dim web_request As Net.HttpWebRequest = Net.HttpWebRequest.Create(url)
            web_response = DirectCast(web_request.GetResponse(), Net.HttpWebResponse)
            Return True
        Catch ex As Exception
            Return False
        Finally
            If Not (web_response Is Nothing) Then web_response.Close()
        End Try
    End Function

    Public Shared Function ExtractDomainFromURL(ByVal sURL As String) As String

        Dim rg As New Regex("://(?<host>([a-z\d][-a-z\d]*[a-z\d]\.)*[a-z][-a-z\d]+[a-z])")

        If rg.IsMatch(sURL) Then
            Return rg.Match(sURL).Result("${host}")
        Else
            Return String.Empty
        End If

    End Function

    Public Shared Function TimestampToDateTime(ByVal UnixTimeStamp As Long) As DateTime
        ' Timestamp is given in GMT timezone. Returns date and time in user's local timezone
        Dim curTimeZone As TimeZone = TimeZone.CurrentTimeZone
        Dim currentOffset As TimeSpan = curTimeZone.GetUtcOffset(DateTime.Now)
        Return (New DateTime(1970, 1, 1, 0, 0, 0)).AddSeconds(UnixTimeStamp + currentOffset.TotalSeconds)
    End Function

    Public Shared Function DateToTimestamp(ByVal dt As Date) As Long
        ' Convert date and time to timestamp
        Dim origin As New Date(1970, 1, 1)
        Dim span As TimeSpan = dt - origin
        Dim seconds As Double = span.TotalSeconds
        Return CType(seconds, Long)
    End Function

    Public Shared Function SortAlpha(ArrString As Object) As Object
        Dim var_temp As String
        For i = UBound(ArrString) To 1 Step -1
            For j = 0 To i - 1
                If ArrString(j) > ArrString(j + 1) Then
                    var_temp = ArrString(j)
                    ArrString(j) = ArrString(j + 1)
                    ArrString(j + 1) = var_temp
                End If
            Next j
        Next i
        Return ArrString
    End Function

    'Replace HTML entities by "normal" characters
    Public Shared Function ReplaceHtmlEntities(ByVal e_txt As String) As String

        ' Create hashtable with all possibilities
        Dim NametoNum As New Hashtable
        NametoNum.Add("&quot;", "34")
        NametoNum.Add("&apos;", "39")
        NametoNum.Add("&amp;", "38")
        NametoNum.Add("&lt;", "60")
        NametoNum.Add("&gt;", "62")
        NametoNum.Add("&nbsp;", "160")
        NametoNum.Add("&iexcl;", "161")
        NametoNum.Add("&curren;", "164")
        NametoNum.Add("&cent;", "162")
        NametoNum.Add("&pound;", "163")
        NametoNum.Add("&yen;", "165")
        NametoNum.Add("&brvbar;", "166")
        NametoNum.Add("&sect;", "167")
        NametoNum.Add("&uml;", "168")
        NametoNum.Add("&copy;", "169")
        NametoNum.Add("&ordf;", "170")
        NametoNum.Add("&laquo;", "171")
        NametoNum.Add("&not;", "172")
        NametoNum.Add("&shy;", "173")
        NametoNum.Add("&reg;", "174")
        NametoNum.Add("&trade;", "8482")
        NametoNum.Add("&macr;", "175")
        NametoNum.Add("&deg;", "176")
        NametoNum.Add("&plusmn;", "177")
        NametoNum.Add("&sup2;", "178")
        NametoNum.Add("&sup3;", "179")
        NametoNum.Add("&acute;", "180")
        NametoNum.Add("&micro;", "181")
        NametoNum.Add("&para;", "182")
        NametoNum.Add("&middot;", "183")
        NametoNum.Add("&cedil;", "184")
        NametoNum.Add("&sup1;", "185")
        NametoNum.Add("&ordm;", "186")
        NametoNum.Add("&raquo;", "187")
        NametoNum.Add("&frac14;", "188")
        NametoNum.Add("&frac12;", "189")
        NametoNum.Add("&frac34;", "190")
        NametoNum.Add("&iquest;", "191")
        NametoNum.Add("&times;", "215")
        NametoNum.Add("&divide;", "247")
        NametoNum.Add("&Agrave;", "192")
        NametoNum.Add("&Aacute;", "193")
        NametoNum.Add("&Acirc;", "194")
        NametoNum.Add("&Atilde;", "195")
        NametoNum.Add("&Auml;", "196")
        NametoNum.Add("&Aring;", "197")
        NametoNum.Add("&AElig;", "198")
        NametoNum.Add("&Ccedil;", "199")
        NametoNum.Add("&Egrave;", "200")
        NametoNum.Add("&Eacute;", "201")
        NametoNum.Add("&Ecirc;", "202")
        NametoNum.Add("&Euml;", "203")
        NametoNum.Add("&Igrave;", "204")
        NametoNum.Add("&Iacute;", "205")
        NametoNum.Add("&Icirc;", "206")
        NametoNum.Add("&Iuml;", "207")
        NametoNum.Add("&ETH;", "208")
        NametoNum.Add("&Ntilde;", "209")
        NametoNum.Add("&Ograve;", "210")
        NametoNum.Add("&Oacute;", "211")
        NametoNum.Add("&Ocirc;", "212")
        NametoNum.Add("&Otilde;", "213")
        NametoNum.Add("&Ouml;", "214")
        NametoNum.Add("&Oslash;", "216")
        NametoNum.Add("&Ugrave;", "217")
        NametoNum.Add("&Uacute;", "218")
        NametoNum.Add("&Ucirc;", "219")
        NametoNum.Add("&Uuml;", "220")
        NametoNum.Add("&Yacute;", "221")
        NametoNum.Add("&THORN;", "222")
        NametoNum.Add("&szlig;", "223")
        NametoNum.Add("&agrave;", "224")
        NametoNum.Add("&aacute;", "225")
        NametoNum.Add("&acirc;", "226")
        NametoNum.Add("&atilde;", "227")
        NametoNum.Add("&auml;", "228")
        NametoNum.Add("&aring;", "229")
        NametoNum.Add("&aelig;", "230")
        NametoNum.Add("&ccedil;", "231")
        NametoNum.Add("&egrave;", "232")
        NametoNum.Add("&eacute;", "233")
        NametoNum.Add("&ecirc;", "234")
        NametoNum.Add("&euml;", "235")
        NametoNum.Add("&igrave;", "236")
        NametoNum.Add("&iacute;", "237")
        NametoNum.Add("&icirc;", "238")
        NametoNum.Add("&iuml;", "239")
        NametoNum.Add("&eth;", "240")
        NametoNum.Add("&ntilde;", "241")
        NametoNum.Add("&ograve;", "242")
        NametoNum.Add("&oacute;", "243")
        NametoNum.Add("&ocirc;", "244")
        NametoNum.Add("&otilde;", "245")
        NametoNum.Add("&ouml;", "246")
        NametoNum.Add("&oslash;", "248")
        NametoNum.Add("&ugrave;", "249")
        NametoNum.Add("&uacute;", "250")
        NametoNum.Add("&ucirc;", "251")
        NametoNum.Add("&uuml;", "252")
        NametoNum.Add("&yacute;", "253")
        NametoNum.Add("&thorn;", "254")
        NametoNum.Add("&yuml;", "255")
        NametoNum.Add("&OElig;", "338")
        NametoNum.Add("&oelig;", "339")
        NametoNum.Add("&Scaron;", "352")
        NametoNum.Add("&scaron;", "353")
        NametoNum.Add("&Yuml;", "376")
        NametoNum.Add("&circ;", "710")
        NametoNum.Add("&tilde;", "732")
        NametoNum.Add("&ensp;", "8194")
        NametoNum.Add("&emsp;", "8195")
        NametoNum.Add("&thinsp;", "8201")
        NametoNum.Add("&zwnj;", "8204")
        NametoNum.Add("&zwj;", "8205")
        NametoNum.Add("&lrm;", "8206")
        NametoNum.Add("&rlm;", "8207")
        NametoNum.Add("&ndash;", "8211")
        NametoNum.Add("&mdash;", "8212")
        NametoNum.Add("&lsquo;", "8216")
        NametoNum.Add("&rsquo;", "8217")
        NametoNum.Add("&sbquo;", "8218")
        NametoNum.Add("&ldquo;", "8220")
        NametoNum.Add("&rdquo;", "8221")
        NametoNum.Add("&bdquo;", "8222")
        NametoNum.Add("&dagger;", "8224")
        NametoNum.Add("&Dagger;", "8225")
        NametoNum.Add("&hellip;", "8230")
        NametoNum.Add("&permil;", "8240")
        NametoNum.Add("&lsaquo;", "8249")
        NametoNum.Add("&rsaquo;", "8250")
        NametoNum.Add("&euro;", "8364")

        ' Search for entities with a regular expression
        Dim myregexp As New Regex("&[a-zA-Z0-9]{2,6}\;", RegexOptions.IgnoreCase)
        If myregexp.IsMatch(e_txt) Then
            Dim elt As Match
            For Each elt In myregexp.Matches(e_txt)
                ' Replace the occurence by the associated value
                e_txt = Replace(e_txt, elt.Value, Chr(NametoNum(elt.Value)))
            Next
        End If

        Return e_txt

    End Function

    Public Shared Function Encrypt(ByVal plainText As String) As String
        Dim passPhrase As String = Reader.SecretKey
        Dim saltValue As String = "mySaltValue"
        Dim initVector As String = "@1B2c3D4e5F6g7H8"
        Dim keySize As Integer = 256
        Dim initVectorBytes As Byte() = Encoding.ASCII.GetBytes(initVector)
        Dim saltValueBytes As Byte() = Encoding.ASCII.GetBytes(saltValue)
        Dim plainTextBytes As Byte() = Encoding.UTF8.GetBytes(plainText)
        Dim password As New Rfc2898DeriveBytes(passPhrase, saltValueBytes)
        Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
        Dim symmetricKey As New RijndaelManaged()
        symmetricKey.Mode = CipherMode.CBC
        Dim encryptor As ICryptoTransform = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes)
        Dim memoryStream As New MemoryStream()
        Dim cryptoStream As New CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)
        cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length)
        cryptoStream.FlushFinalBlock()
        Dim cipherTextBytes As Byte() = memoryStream.ToArray()
        memoryStream.Close()
        cryptoStream.Close()
        Dim cipherText As String = Convert.ToBase64String(cipherTextBytes)
        Return cipherText
    End Function

    Public Shared Function Decrypt(ByVal cipherText As String) As String
        Dim passPhrase As String = Reader.SecretKey
        Dim saltValue As String = "mySaltValue"
        Dim initVector As String = "@1B2c3D4e5F6g7H8"
        Dim keySize As Integer = 256
        ' Convert strings defining encryption key characteristics into byte
        ' arrays. Let us assume that strings only contain ASCII codes.
        ' If strings include Unicode characters, use Unicode, UTF7, or UTF8
        ' encoding.
        Dim initVectorBytes As Byte() = Encoding.ASCII.GetBytes(initVector)
        Dim saltValueBytes As Byte() = Encoding.ASCII.GetBytes(saltValue)
        ' Convert our ciphertext into a byte array.
        Dim cipherTextBytes As Byte() = Convert.FromBase64String(cipherText)
        ' First, we must create a password, from which the key will be
        ' derived. This password will be generated from the specified
        ' passphrase and salt value. The password will be created using
        ' the specified hash algorithm. Password creation can be done in
        ' several iterations.
        Dim password As New Rfc2898DeriveBytes(passPhrase, saltValueBytes)
        ' Use the password to generate pseudo-random bytes for the encryption
        ' key. Specify the size of the key in bytes (instead of bits).
        Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
        ' Create uninitialized Rijndael encryption object.
        Dim symmetricKey As New RijndaelManaged()
        ' It is reasonable to set encryption mode to Cipher Block Chaining
        ' (CBC). Use default options for other symmetric key parameters.
        symmetricKey.Mode = CipherMode.CBC
        ' Generate decryptor from the existing key bytes and initialization
        ' vector. Key size will be defined based on the number of the key
        ' bytes.
        Dim decryptor As ICryptoTransform = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes)
        ' Define memory stream which will be used to hold encrypted data.
        Dim memoryStream As New MemoryStream(cipherTextBytes)
        ' Define cryptographic stream (always use Read mode for encryption).
        Dim cryptoStream As New CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)
        ' Since at this point we don't know what the size of decrypted data
        ' will be, allocate the buffer long enough to hold ciphertext;
        ' plaintext is never longer than ciphertext.
        Dim plainTextBytes As Byte() = New Byte(cipherTextBytes.Length - 1) {}
        ' Start decrypting.
        Dim decryptedByteCount As Integer = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length)
        ' Close both streams.
        memoryStream.Close()
        cryptoStream.Close()
        ' Convert decrypted data into a string.
        ' Let us assume that the original plaintext string was UTF8-encoded.
        Dim plainText As String = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount)
        ' Return decrypted string.
        Return plainText
    End Function

End Class
